package Page
{
    import Regex.Regex;
    
    import TextFile.TextFile;
    
    import flash.filesystem.File;
    
    import mx.collections.ArrayCollection;
//    import mx.core.Application;
    
    [Event(name=ProgressEvent.COMPLETE, type="flash.events.ProgressEvent")]
//    [Event(name=TextEvent.TEXT_INPUT, type="flash.events.TextEvent")]

    [Bindable]
	public class Page extends File
	{
        private static const THUMB_FOLDER_NAME:String = "thumbs";
        private static const THUMB_HEIGHT:Number = 200;
        private static const THUMB_WIDTH:Number = 125;
        
        private var         _index:uint;
        private var         _section:String = "";
        private var         _pagenumber:String = "";
        private var         _species:String = "";
        private var         _remark:String = "";
//        private var         _newfilename:String = "";
        private var         _textfile:TextFile;
//        private var         _found_index:int;
//        private var         _found_string:String;
//        private var         _is_reverted:Boolean = false;

		public function Page(index:uint, pfile:File, charset:String) {
		    _index = index;
		    super(pfile.nativePath);
            _textfile = new TextFile(textfilepath, "utf-8");
		}
		
		public function MatchCount(re:Regex):uint {
		    var str:String = this.Text;
		    if(re.unaccent) {
		        
		    }
		    return re.MatchCount(this.Text);
//		    var r:RegExp = new RegExp(re.Pattern, 
//		      "g" + (re.ignoreCase ? "i" : "")
//		      + (re.multiline ? "m" : "")
//		      + (re.dotall ? "s" : ""));
//            var a:ArrayCollection = re.Matches(Text);
//            var a:Array = this.Text.match(re.re);
//		    if(a && a.length > 0) {
//		        return a.length;
//		    } else {
//		        return 0;
//		    }
		}

        public function dehyphenate(): void {
            var re:RegExp = new RegExp(/.*[\wä]-$/gm);
            var s:String = this.Text;
            var o:Object = re.exec(s);
            for( ; o ; o = re.exec() ) {
                var s0:String = o[0] as String;
                var a0:Array = s0.split(/[^\wä]+/);
                var w0:String = a0[a0.length-2];
                var a1:Array = s.substr(re.lastIndex+1).match(/[\wä]+/m);
                if(a1) {
                    var w1:String = a1[0];
                    var w:String = w0 + w1;
//                    trace(w);
                }
            }
        }	
        	
		public function get index():uint {
		    return this._index;
		}
		
        private function get rows():Array {
            return Text.split("\n");    
        }

		public function get WordsArray():Array {
		    var a:Array;
		    var aret:Array = new Array();
		    var l:int;
            var s:String;
            var s0:String = "";
		    
		    // multiple hyphens to one space - not a joined word
		    for each( var r:String in this.rows ) {
                // replace (not-'-period-comma-alnum-hyphen)s with spaces
                // $line =~ s/[^'\.,\p{Alnum}-]/ /g;
                // only keep (period-'-alphanum-comma) and some high-range stuff
                // warning - guiguts de-utf8's the line first
                r = r.replace(/[^\'\.,a-z0-9\xe0-\xff-]/ig, " ");

                // replace double-hyphen with a space
                // $line =~ s/--/ /g;
                r = r.replace(/--/g, " ");
                
                // replace comma following non-digit with a space
                // $line =~ s/(\D),/$1 /g;
                r = r.replace(/(\D),/g, "$1 ");
                
                // replace comma before non-digit with a space
                // $line =~ s/,(\D)/ $1/g;
                r = r.replace(/,(\D)/g, " $1");
                
                r = r.replace(/[,\.\']$/, "");
                r = r.replace(/[,\.\'](\s)/, "$1"); 
                        
                
                
                // split on \s
                // @words = split( /\s+/, $line );
                
                /*
		        r = r.replace( /-{2,}/g, " " );
                r = r.replace(/(\D),/gm, "$1 ");
                r = r.replace(/[^a-zA-Z0-9\xe0-\xff\.,'-\s]+/g, " ");
                r = r.replace(/\.(\W+)/mg, " $1");
                */
                a = r.split(/\s+/);
                l = a.length;
                
                if( l == 0 ) {   // empty row
                    // maybe pick up hyphenated word from last row
                    if( s0.length > 0 ) {
                        aret = aret.concat( s0 );
                        s0 = "";
                    }
                    // on to the next row
                    continue;
                }

                // row has text
                // anything left at end of last row?
                if( s0.length > 0 ) {
                    // pull the first word and join them
                    s0 += ( "*" + a.shift() );
                    // add the resulting string
                    aret = aret.concat( s0 );
                    // and reset the hyphenated string
                    s0 = "";
                }
                
                // if we've depleted the arraay, loop again.
                l = a.length;
                if( l == 0 ) {
                    continue;
                }

                // hyphenated word at end?
                s0 = a[l-1];
                if( s0.substr( -1 ) != "-" ) {
                    // no? unset test string from end
                    s0 = "";
                }
                // otherwise keep it for next loop and pop it off.
                else {
                    a.pop();
                }      
                aret = aret.concat( a );
		    }
		    // if anything left hyphenated at end of page, add it
		    if( s0.length > 0 ) {
                aret = aret.concat( s0 );
		        s0 = "";
		    }
            return aret ;
            // commas not between digits to a space
//            t = t.replace(/(\D),/g, "$1 ");
//            t = t.replace(/,(\D)/g, " $1");
//            t = t.replace(/([^\d ?])\./g, "$1 ");
//            t = t.replace(/\.(\D)/g, " $1");
            
//            t = t.replace(/[^a-zA-Z0-9\xe0-\xff\.,'-\s]+/g, " ");
            // multiple spaces to one
//            t = t.replace(/\s+/g, " ");
//            var a:Array = t.split(/ /);    
//            for each(var wd:String in a) {
//                wd = wd.replace(/[\.\',-']+$/, "");
//                wd = wd.replace(/^[\.\',-']+/, "");
//                if(! wd.length) {
//                    continue;
//                }
                
//                if(! _words[wd]) {
//                    _words[wd] = 1;
//                } else {
//                    _wc++;
//                    _words[wd]++;
//                }
//            }
//                    trace(_wc, i.name, t);
		}
//		public function Matches(re:Regex):ArrayCollection {
//		    return re.Matches(Text);
//		}
		
//		public function LastMatch(re:Regex):Boolean {
//		     if(this.MatchCount(re) > 0) {
//		         var ac:ArrayCollection = this.Matches(re);
//		         var o:Object = ac.getItemAt(ac.length-1);
//		         _found_string = o[0];
//		         _found_index = o.index;
//		         return true;
//		     } else {
//                 _found_string = "";
//                 _found_index = -1;
//                 return false;
//		     }
//		}
//		
//		public function NextMatch(re:Regex, index:int):Boolean {
//            re.lastIndex = index ;
//            var o:Object = re.NextMatch(Text);
//            if(! o) {
//                _found_index = -1;
//                _found_string = "";
//                return false;
//            }
//            _found_index = o.index;
//            _found_string = o[0] as String;
//            return true;
//		}
//		
//		public function PrevMatch(re:Regex, index:int):Boolean {
//		    var ma:ArrayCollection = Matches(re);
//		    if(ma.length == 0) {
//                _found_index = -1;
//                _found_string = "";
//		        return false;
//		    }
//		    var m:Object = ma[ma.length-1];
//            _found_string = m[0] as String;
//            _found_index = m.index;
//            return true;
////		    for each(var o:Object in Matches(re)) {
////		        if(o.index < index) {
////		             _found_string = o[0] as String;
////		             _found_index = o.index;
////		        }
////		    }   
////		    return (_found_index >= 0);
//		}
		
		public function get FileName():String {
		    return this._textfile.name ;
		}
		
		public function set FileName(s:String):void {
		    
		}
		
		public function get imageCaption():String {
	        return name;
		}

        public function get section():String {
            return _section;
        }
        
        public function set section(pStr:String):void {
            _section = pStr;     
//            setNewFileName();  
        }
        
        public function get pageNumber():String {
            return _pagenumber;
        }
        
        public function set pageNumber(pStr:String):void {
            _pagenumber = pStr.replace(" ", "");            
//            setNewFileName();  
        }
        public function get species():String {
            return _species;
        }
        
        public function set species(pStr:String):void {
            _species = pStr;            
//            setNewFileName();  
        }

        public function get remark():String {
            return _remark;
        }
        
        public function set remark(pStr:String):void {
            _remark = pStr;            
        }

        private function get textName():String {
        	return name.replace(extension, "txt");
        }
        
        public function get Text():String {
//            if(this.isText)
                return _textfile.Text;
//            else
//                return "No text available for this page."
//            if(_textfile.exists) {
//                return _textfile.text;
//            } else {
//                return "";
//            }
        }
        
        public function set HtmlText(s:String):void {
        }
        
        public function get HtmlText():String {
            if(! isText) {
                return "<h3>No text available for this page.</h3>"
            }
            
            var stext:String = Text;
            var ptr:int = 0;
            var hstr:String = "";
            var s:String;

            stext = stext.replace(/\&/g, "&amp;");
            hstr = "<html>\n" + 
                    "<head>\n" + 
                    "<title>Preview</title>\n" + 
                    "<style type='text/css'>\n" + 
                    ".basic {fontSize: 1em;}\n" +
                    "I { color: red } \n" + 
                    "SC {color: blue; font-variant: small-caps} \n" + 
                    ".quote { color: red } \n" +
                    "A {text-decoration: underline}\n</style>\n\n" +
                    "<script type='text/javascript'>\n" +
                    "window.onload = function() {\n" +
                    "var ctl = document.getElementById('atext');\n" +
                    "ctl.style.fontSize='16px';\n" +
                    "}\n\n" + 
                    "function bigger() {\n" + 
                        "var ctl = document.getElementById('atext');\n" +
                        "var sz = ctl.style.fontSize;\n" +
                        "var isz = parseInt(sz);\n" +
                        "if(isz >= 36) {\n" + 
                        "return;\n" + 
                        "}\n" +
                        "isz++;\n" +
                        "ctl.style.fontSize = isz.toString() + 'px';\n" +
                    "}\n" + 
                    "function setFontFamily(fname) {\n" + 
                        "var ctl=document.getElementById('atext');\n" + 
                        "ctl.style.fontFamily = fname;\n" + 
                    "}\n\n" +
                    "function setFontSize(fsize) {\n" + 
                        "var ctl=document.getElementById('atext');\n" + 
                        "ctl.style.fontSize = fsize;\n" + 
                    "}\n\n" +
                    "function smaller() {\n" + 
                        "var ctl = document.getElementById('atext');\n" +
                        "var sz = ctl.style.fontSize;\n" +
                        "var isz = parseInt(sz);\n" +
                        "if(isz >= 36) {\n" + 
                        "return;\n" + 
                        "}\n" +
                        "isz--;\n" +
                        "ctl.style.fontSize = isz.toString() + 'px';\n" +
                    "}\n" + 
                    "</script>\n" +
                    "</head>\n" +
                    "<body>\n" + 
                    "<div id='atext' class='basic'>\n" + 
                    "<pre>\n";
//            var m:ArrayCollection = mx.core.Application.application.AppContext.QuotesRegex.Matches(stext);
//            for each(var o:Object in m) {
//                s = stext.substring(ptr, o.index);
//                hstr += (s + "<span class='quote'>" + o[0] + "</span>");
//                ptr = (o.index + o[0].length);
//            }
//            hstr += stext.substr(ptr);
            hstr += stext;            
            hstr +="</pre>\n" + 
                    "</div>\n" + 
                    "</body>\n" + 
                    "</html>";
            return hstr;
        }
        
        public function set Text(str:String):void {
            if(! _textfile.exists || _textfile.Text == str) {
                return;
            }
            
            _textfile.Text = str;
//            this.dispatchEvent(new TextEvent(TextEvent.TEXT_INPUT, false, true, oldtext));
        }
        
        public function get newFileName():String {
            if(_section == "" && _pagenumber == "" && _species == "") {
                return "";
            }
            var ret:String = _section + _pagenumber;
            if(ret.length > 0 && species.length > 0)
                ret += "-";
            ret += _species;
            ret += ".";
            ret += extension;
            return ret;
        }
        
//        public function set newFileName(pstr:String):void {
//            _newfilename = pstr;
//        }
        
        public function get newTextName():String {
        	return this.newFileName.replace(extension, "txt");
        }
        
//        public function setNewFileName():void {
//            if(_section == "" && _pagenumber == "" && _species == "") {
//                _newfilename = "";
//                return;
//            }
//            var ret:String = _section + _pagenumber;
//            if(ret.length > 0 && species.length > 0)
//                ret += "-";
//            ret += _species;
//            ret += ".";
//            ret += extension;
//            _newfilename = ret;
//        }
        
        public function setPageNumber(from:String, offset:int):void {
            var mode:String = inferMode(from);
            var i:int = 0;
            switch(mode) {
                case "i":
                    i = parseInt(from, 10) + offset;
                    pageNumber = ("00000" + i.toString()).substr(-from.length);
                    return;
                    
                case "b":
                    i = parseInt(from,10) + (offset + 1)/2 ;
                    pageNumber = ("00000" + i.toString() + (offset % 2 === 0 ? "b" : "a")).substr(-from.length);
                    return;
                   
                case "a":
                    i = parseInt(from,10);
                    i += (offset)/2;
                    pageNumber = ("00000" + i.toString() + (offset % 2 === 0 ? "a" : "b")).substr(-from.length);
                    return;
                    
                default:
                    return;
            }
        }
        
        private function get thumbFolderPath():String {
             return buildPath(folderPath, THUMB_FOLDER_NAME);
        }

        private function get thumbnailFile():File {
        	var p:String = buildPath(thumbFolderPath, name);
            var f:File = resolvePath(p);
            if(!f || !f.exists || f.isDirectory) {
                return null;
            } else {
                return f;
            }
        }
        
        private function get thumbnailExists():Boolean {
        	return (thumbnailFile !== null && thumbnailFile.exists);
        }
        
        public function get thumbnailUrl():String {
            var s:String;
        	if(thumbnailExists) {
	            s = thumbnailFile.url;
	        } else {
        		s = this.url;
        	}
        	return s;
        }
        
        public function get ImageUrl():String {
            return url;
        }
        
        public function set ImageUrl(pstr:String):void {
            
        }
        
        public function set thumbnailUrl(pStr:String):void {
        }
        
        public function get thumbnailHtml():String {
            var s:String = "<img src='" + this.thumbnailUrl + "' style='height: 100%' />";
            return s;
        }

        public function set thumbnailHtml(pStr:String):void {
        }
        
        private static function isinteger(istr:String):Boolean {
            if(istr.length === 0) {
                return false;
            }
            var re:RegExp = /\D/;
            var r:int = istr.search(re);
            // if there are non-integers, return false
            return r === -1;
        }
    
        private static function istype2(istr:String):Boolean {
            var re:RegExp = /\d+[ab]/;
            var r:int = istr.search(re);
            return r !== -1;
        }
    
        private static function inferMode(str:String):String {
            if(isinteger(str)) {
                return 'i';
            }
            if(istype2(str)) {
                return str.substr(-1) === "a" ? "a" : "b";
            }
            return '';
        }
        
        private function get folderPath():String {
        	return parent.nativePath;
        }
        
        public function get path():String {
            return nativePath.toString();    
        }
        

        public static function buildPath(p1:String, p2:String):String {
        	for( ; p1.length > 0 && ( p1.substr(-1) === "\\" || p1.substr(-1) === "/"); ) {
        		p1 = p1.substr(0, p1.length-1);
        	}
        	for( ; p2.length > 0 && ( p2.substr(0, 1) === "\\" || p2.substr(0, 1) === "/"); ) {
        		p2 = p2.substr(1);
        	}
        	return p1 + "/" + p2;
        }
        
        private function zipPath():String {
            var f:File = new File(folderPath);
            var s:String = buildPath(folderPath, f.name);
            f = f.resolvePath(s);
            if(! f.exists) {
            	f.createDirectory();
            }
        	s = buildPath(s, f.name + "-page-images");
        	f = f.resolvePath(s);
            if(! f.exists) {
                f.createDirectory();
            }
        	
        	return s;
        }
        
        public function clear():void {
            remark = "";
            section = "";
            pageNumber = "";
            species = "";	
        }
        
        private function get textfilepath():String {
            return buildPath(folderPath, textName);
        }
        
        public function get isText():Boolean {
            return _textfile.exists;
        }
        
        public function get isTextY():String {
        	return isText ? "Yes": "";
        }
        
        public function ReplaceAll(re:Regex):void {
//            if( re.IsQuote ) {
//                return;
//            }
//            
//            if(re.Matches(Text) && re.Matches(Text).length > 0) {
            if(this.MatchCount(re)) {
                var s:String = re.ReplaceString(this.Text);
                this.Text = s;
            }
////            if(Text.search(re.re) >= 0) {
////                var s:String = Text.replace(re.Pattern, re.ReplacePattern);
//                var s:String = re.RegExpReplace(Text);
////                var s:String = Text.replace(re.re, re.ReplacePattern);
//                Text = s;
//            }
        }
//        
        public function copyExport():void {
        	if(newFileName === "") {
        		return;
        	}
        	// copy image file
            var topath:String = buildPath(zipPath(), newFileName);
            var fto:File = new File(topath);
        	copyToAsync(fto, true);
        	// copy text file
             var totextpath:String = buildPath(zipPath(), newTextName);
            this._textfile.saveLatin1ToPath(totextpath);
        }
    }
}
